/*******************************************************************************
 * Copyright (c) 2010 Gary Yund {OTHER COPYRIGHT OWNERS}.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Gary Yund - initial API and implementation and/or initial documentation
 *******************************************************************************/

#import "BB_CSVParser.h"

#import "BB_Logger.h"

@interface BB_CSVParser (private)

-(NSArray *)getCSVRow:(NSString*)aRowString;

@end

@implementation BB_CSVParser (private)

/**
 
 This function was pulled from: http://www.macresearch.org/cocoa-scientists-part-xxvi-parsing-csv-data
 
 Special thanks to:
 Author: Drew McCormack
 Web Site: www.maccoremac.com, www.macanics.net
 
 Minor modifications were made since the original function was a category of
 NSString.
 
 */
-(NSArray *)getCSVRow:(NSString*)aRowString {
    NSMutableArray *rows = [NSMutableArray array];
    
    // Get newline character set
    NSMutableCharacterSet *newlineCharacterSet = (id)[NSMutableCharacterSet whitespaceAndNewlineCharacterSet];
    [newlineCharacterSet formIntersectionWithCharacterSet:[[NSCharacterSet whitespaceCharacterSet] invertedSet]];
    
    // Characters that are important to the parser
    NSMutableCharacterSet *importantCharactersSet = (id)[NSMutableCharacterSet characterSetWithCharactersInString:@",\""];
    [importantCharactersSet formUnionWithCharacterSet:newlineCharacterSet];
    
    // Create scanner, and scan string
    NSScanner *scanner = [NSScanner scannerWithString:aRowString];
    [scanner setCharactersToBeSkipped:nil];
    while ( ![scanner isAtEnd] ) {        
        BOOL insideQuotes = NO;
        BOOL finishedRow = NO;
        NSMutableArray *columns = [NSMutableArray arrayWithCapacity:10];
        NSMutableString *currentColumn = [NSMutableString string];
        while ( !finishedRow ) {
            NSString *tempString;
            if ( [scanner scanUpToCharactersFromSet:importantCharactersSet intoString:&tempString] ) {
                [currentColumn appendString:tempString];
            }
            
            if ( [scanner isAtEnd] ) {
                if ( ![currentColumn isEqualToString:@""] ) [columns addObject:currentColumn];
                finishedRow = YES;
            }
            else if ( [scanner scanCharactersFromSet:newlineCharacterSet intoString:&tempString] ) {
                if ( insideQuotes ) {
                    // Add line break to column text
                    [currentColumn appendString:tempString];
                }
                else {
                    // End of row
                    if ( ![currentColumn isEqualToString:@""] ) [columns addObject:currentColumn];
                    finishedRow = YES;
                }
            }
            else if ( [scanner scanString:@"\"" intoString:NULL] ) {
                if ( insideQuotes && [scanner scanString:@"\"" intoString:NULL] ) {
                    // Replace double quotes with a single quote in the column string.
                    [currentColumn appendString:@"\""]; 
                }
                else {
                    // Start or end of a quoted string.
                    insideQuotes = !insideQuotes;
                }
            }
            else if ( [scanner scanString:@"," intoString:NULL] ) {  
                if ( insideQuotes ) {
                    [currentColumn appendString:@","];
                }
                else {
                    // This is a column separating comma
                    [columns addObject:currentColumn];
                    currentColumn = [NSMutableString string];
                    [scanner scanCharactersFromSet:[NSCharacterSet whitespaceCharacterSet] intoString:NULL];
                }
            }
        }
        if ( [columns count] > 0 ) [rows addObject:columns];
    }
    
    return rows;
}

@end


@implementation BB_CSVParser

@synthesize csvTable;

-(BB_CSVParser*)initWithContentsOfFile: (NSString*)path{
    NSString *fileData = [NSString stringWithContentsOfFile:path];
    self.csvTable = [ self getCSVRow: fileData ];
    
    [ self resetRowCount ];
    
    return self;
}

-(NSArray*)getColumnNames
{   
    if( [csvTable count] > 0 )
    {
        return [[ self csvTable] objectAtIndex:0];
    }
    else
    {
        return nil;
    }
}

-(NSArray*)getNextRecord
{
    if(rowCount < [csvTable count] )
    {
        return [[ self csvTable] objectAtIndex:rowCount++];
    }
    else
    {
        return nil;
    }
    
}

-(void)resetRowCount
{
    rowCount = 1;
}


@end
